﻿using System;
using CrystalDecisions.Enterprise.Admin;
using CrystalDecisions.Enterprise.Desktop;

using System.Management;
using System.Management.Instrumentation;

namespace BO.Management
{
    public class ServerProvider : BaseSystemObjectProvider<Server>
    {

        #region "Private members"

        public const Int32 DEFAULT_WAITING_STATUS = 60;

        #endregion

        /// <summary>
        /// Default constructor required the LogonProvider used to connect to BO Cms
        /// </summary>
        /// <param name="logonProvider"></param>
        public ServerProvider(LogonProvider logonProvider)
            : base(logonProvider)
        {

        }

        /// <summary>
        /// Get the kind of this object : Server
        /// </summary>
        public override ObjectKind Kind
        {
            get
            {
                return ObjectKind.Server;
            }
        }


        ///// <summary>
        ///// Disable a job server and return its state
        ///// </summary>
        ///// <param name="server"></param>
        ///// <param name="timeout"></param>
        ///// <returns></returns>
        //public Server DisableServer(Server server, Int32 timeout)
        //{
        //    if (server == null) throw new ArgumentNullException("server");

        //    //Disable the server
        //    if (!server.Disabled)
        //    {
        //        WriteVerbose(String.Format("The Server {0} will be disabled", server.Title));
        //        server.Disabled = true;
        //        this.Commit(server);
        //    }
        //    else
        //    {
        //        WriteVerbose(String.Format("The Server {0} is already disabled", server.Title));
        //    }


        //    //if this server was not disable, query to have its status
        //    if (!server.CurrentDisabledState)
        //    {

        //        //Wait CurrentDisableState during timeout 
        //        DateTime serverStatusQuery = DateTime.Now;
        //        if (timeout <= 0) timeout = DEFAULT_WAITING_STATUS;

        //        while (!server.CurrentDisabledState)
        //        {

        //            if (serverStatusQuery.AddSeconds(timeout) < DateTime.Now)
        //            {
        //                break;
        //            }

        //            WriteVerbose(String.Format("The Server {0} is not yet disabled", server.Title));
        //            System.Threading.Thread.Sleep(1000);
        //            server = this.GetObject(server.ID);

        //        }
        //    }

        //    return server;

        //}




        //public Server StopServer(Server server, Int32 timeout, Boolean force)
        //{
        //    if (server == null) throw new ArgumentNullException("server");

        //    //First disable the server
        //    if (!server.Disabled)
        //    {
        //        WriteVerbose(String.Format("The Server {0} will be disabled", server.Title));
        //        server.Disabled = true;
        //        this.Commit(server);
        //    }
        //    else
        //    {
        //        WriteVerbose(String.Format("The Server {0} is already disabled", boeObject.Title));
        //    }

        //}


        /// <summary>
        /// Kill a job server when it is unresponsive
        /// </summary>
        /// <param name="server"></param>
        /// <returns></returns>
        public Boolean Kill(Server server)
        {
            Int32 serverPID = (Int32)server.Properties["SI_PID"].Value;
            String serverHost = (String)server.Properties["SI_SERVER_NAME"].Value;
            String executionHost = System.Environment.MachineName;

            if (serverHost.ToLower().CompareTo(executionHost.ToLower()) == 0)
            {
                //Local execution
                System.Diagnostics.Process processServer = System.Diagnostics.Process.GetProcessById(serverPID);
                if (processServer != null)
                {
                    processServer.Kill();
                    processServer.WaitForExit();
                }
                return true;
            }
            else
            {
                //remote execution
                ManagementScope scope = new ManagementScope(String.Format("\\\\{0}\\root\\cimv2", serverHost));
                ObjectQuery query = new ObjectQuery(String.Format("SELECT * FROM Win32_Process WHERE ProcessID={0}", serverPID));

                scope.Connect();
                using(ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query))
                {
                    ManagementObjectCollection results = searcher.Get();
                    if (results == null || results.Count == 0)
                    {
                        return false;
                    }
                    else
                    {
                        foreach (ManagementObject result in results)
                        {
                            result.InvokeMethod("Terminate", null);
                        }
                    }
                }

            }

            return true;
        }

        public JobServerDestination Test(Server server)
        {
            JobServerAdmin admSrv = new CrystalDecisions.Enterprise.Admin.JobServerAdmin(server.ServerAdmin);
            return admSrv.Destinations[1];
        }
    }
}
